Cocoa中View的层级与鼠标事件的派发和处理

2017-8-1

View的层级

在Interface Builder中,约在下面的View层级约高

如下图

TestView2就显示在TestView1之上

在使用代码动态添加View时,Cocoa并不能为我们保证View的层级,比如我往TestView1里面添加一个subview,TestView2可能就显示在TestView1之上了。

这时候我们需要通过代码来手动排版一下。

如下

[self.testview2 removeFromSuperview];
[self.rootView addSubview:self.testview2 positioned:NSWindowAbove relativeTo:nil];

鼠标事件的派发与处理

查找需要派发鼠标事件的View

事件最开始由当前 NSWindow 的 sendEvent:方法发送出去

通过NSView的- (nullable NSView *)hitTest:(NSPoint)point 方法,找到接收鼠标事件的View。

hitTest的调用过程是按照View显示的层级,从最外层的View开始,然后依次往下调用。最后会找到最深的并且显示在最前面的那个View。

父View的hitTest调用子类的hitTest来层层寻找。默认的,最后的子类在响应的point找不到更小的子类了就会返回自己。

View处理鼠标事件

找到需要派发的NSView后,就会发送响应的方法,比如- (void)mouseDown:(NSEvent *)event- (void)mouseDragged:(NSEvent *)event

通过自定义的View继承自NSView,重载这些方法,我们可以处理鼠标的事件。

继续派发

这里需要注意的是,在时间处理方法中,比如- (void)mouseDown:(NSEvent *)中,如果调用了[super mouseDown:event];

事件会继续派发下去

hitTest会继续执行,往下寻找下一个需要派发事件的View

其他